//#pragma once
#ifndef FIFO_HPP

#define FIFO_HPP

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define FIFO_FILE "./fifo"

#define EXIT_FAILURE 1

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

// #define ERR_EXIT(m) \
//     do \
//     { \
//         perror(m); \
//         exit(EXIT_FAILURE); \
//     } while(0)

#define PATH "."

const int gmode = 0666;

class Fifo_Make
{
private:
    void Create(const char* s)
    {
        int ret = mkfifo(s, gmode);

        if (ret < 0)
        {
            ERR_EXIT("mkfifo");
        }
    }

public:
    Fifo_Make(std::string s)
        :_path(PATH)
        ,_name(s)
    {
        _filena = _path + "/" + _name;
        Create(_filena.c_str());
    }

    ~Fifo_Make()
    {
        unlink(_filena.c_str());
    }

    const char *str()
    {
        return _filena.c_str();
    }

private:
    std::string _path;
    std::string _name;
    std::string _filena;
};

class Fifo_Oper
{
private:
    void Write_Pipe()
    {
        int i = 0;
        std::string message;
        while(true)
        {
            std::getline(std::cin,message);

            message += "[" + std::to_string(i) + "]";

            int n = write(_fd,message.c_str(), message.size());

            if (n < 0)
            {
                ERR_EXIT("WritePipe");
            }
            message.clear();
            ++i;
        }
    }

    void Read_Pipe()
    {
        char buffer[1024];

        while(true)
        {
            int n = read(_fd, buffer, sizeof(buffer) - 1);
        
            if (n > 0)
            {
                buffer[n] = 0;
            }
            else if(n == 0)
            {
                ERR_EXIT("READ");
            }
            // 这个是系统方面的问题与我们无关。
            else
            {
                break;
            }

            std::cout << buffer << std::endl;
        }
    }

public:
    Fifo_Oper(const char* s)
        : _fifona(s)
    {
        // O_CREAT | O_WRONLY | O_RDONLY
        // only选项互不兼容。
        _fd = open(_fifona.c_str(), O_CREAT | O_RDWR, gmode);
        if (_fd < 0)
        {
            ERR_EXIT("open");
        }
    }

    ~Fifo_Oper()
    {
        close(_fd);
        //unlink(_str.c_str());
    }

    void Read()
    {
        Read_Pipe();
    }

    void Write()
    {
        Write_Pipe();
    }

private:
    std::string _fifona;
    int _fd;
};

#endif